#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define DELIM " \t"
extern char **environ;
int quit = 0;
int lastcode = 0;
char pwd[1024];
char *commandline[1024];
char *argv[128];
char myenv[128];
const char *GetUsername()
{
    return getenv("USER");
}
const char *GetHostname()
{
    return getenv("HOSTNAME");
}

char *GetPwd()
{
    return getcwd(pwd, sizeof(pwd));
}

void interact(char *cline, int size)
{
    printf(LEFT "%s@%s %s" RIGHT LABLE "\n", GetUsername(), GetHostname(), GetPwd());
    char *s = fgets(cline, size, stdin);
    // assert(s);
    (void)s;
    cline[strlen(cline) - 1] = '\0';
    // printf("%s\n", cline);
}

int splitstring(char *cline, char *_argv[])
{
    int i = 0;
    // printf("interact finish\n");
    argv[i] = strtok(cline, DELIM);
    // printf("argv[%d]: %s\n",i,_argv[i]);
    i++;
    while (_argv[i++] = strtok(NULL, DELIM))
        ;
    // {
    //     printf("argv[%d]: %s\n",i,_argv[i]);
    //     i++;
    // };
    return i - 1;
}
int buildcommand(int _argc, char *_argv[])
{
    if (_argc == 2 && strcmp(_argv[0], "cd") == 0)
    {
        // 改变路径,切换到argv[1]的指定的目录
        chdir(argv[1]);
        // 获取当前工作目录的路径
        GetPwd();
        // 将获取到的当前工作目录pwd写入环境变量PWD中，以更新当前工作目录的环境变量记录
        sprintf(getenv("PWD"), "%s", pwd);
    }
    else if (_argc == 2 && strcmp(_argv[0], "export") == 0)
    {
        strcpy(myenv, argv[1]);
        putenv(myenv);
    }
    else if (_argc == 2 && strcmp(_argv[0], "echo") == 0)
    {
        // printf("enter echo\n");
        if (strcmp(_argv[1], "$?") == 0)
        {
            printf("%d\n", lastcode);
            lastcode = 0;
        }
        else if (*_argv[1] == '$')
        {
            char *val = getenv(_argv[1] + 1);
            if (val)
                printf("%s\n", val);
        }
        else
        {
            printf("%s\n", _argv[1]);
        }
        return 1;
    }

    //特殊处理ls
    if(strcmp(_argv[0],"ls")==0)
    {
        _argv[_argc]="--color";
        _argc++;
        _argv[_argc]=NULL;
    }
    return 0;
}

void NormalExcute(char *_argv[])
{

    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return;
    }
    else if (id == 0) // child
    {
        // 让子进程执行命令
        execvp(_argv[0], _argv);
        exit(1);
    }
    else // father
    {
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if (id == rid)
        {
            lastcode = WEXITSTATUS(status);
        }
    }
}

int main()
{
    while (!quit)
    {
        // 一： 交互问题，获取命令行 ls -a -l >myfile /ls -a -l >>myfile /cat <file.txt
        interact(commandline, sizeof(commandline));
        // 二：子串分割问题
        int argc = splitstring(commandline, argv);
        if (argc == 0)
            continue;
        // 指令的判断
        // 内键命令，本质就是shell内部的一个函数
        // cd export echo
        // printf("argc:%d\n",argc);
        // printf("splitstring finish\n");
        // printf("srgv[1]:%s\n",argv[1]);
        int n = buildcommand(argc, argv);
        if (!n)
            NormalExcute(argv);
    }
    return 0;
}